<?php
// +----------------------------------------------------------------------
// | Created by Sublime: [ Cj丶Admin ]
// +----------------------------------------------------------------------
// | Copyright (c) 2021~20223[chenjia] All rights reserved.
// +----------------------------------------------------------------------
// | SiteUrl: http://www.99dn.cn
// +----------------------------------------------------------------------
// | Author: Conqweal <150672834@qq.com>
// +----------------------------------------------------------------------
// | Date: 2021/12/22 0026
// +----------------------------------------------------------------------
// | Description:会员接口 
// +----------------------------------------------------------------------
namespace Paypal;
use PayPal\Api\Amount;
use PayPal\Api\Details;
use PayPal\Api\InputFields;
use PayPal\Api\Item;
use PayPal\Api\ItemList;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
use PayPal\Api\Presentation;
use PayPal\Api\RedirectUrls;
use PayPal\Api\Transaction;
use PayPal\Api\WebProfile;
use PayPal\Auth\OAuthTokenCredential;
use PayPal\Exception\PayPalConnectionException;
use PayPal\Rest\ApiContext;
use think\Exception;
use think\facade\Db;
use support\Request; 

class Paypal
{
    // sandbox 开发环境
    // const clientId = 'xxxxxxxxxx';
    // const clientSecret = 'xxxxxxxx';
    protected $noNeedLogin = ['index'];
    protected $noNeedRight = '*'; 
    const Currency     = 'USD'; //币种 美元
    protected $PayPal;
    protected $order_number;

    public function __construct()
    {
        $config = getConfig('paypal');

        $this->PayPal = new ApiContext(
            new OAuthTokenCredential(
                $config['client_id'],
                $config['client_secret']
            )
        );

        //正式环境启用        
        if(!$config['sandbox']){
            $this->PayPal->setConfig(
                array(
                    'mode' => 'live',
                )
            );
        }
    }

    public function createForm($pm)
    {

        // 商品名称
        $product = $pm['product'];

        // 总价
        $price = $pm['price'];

        // 运费
        $shipping = 0;

        // 商品描述
        $description = $pm['description'];
        $key         = $pm['rar_id'];
        return $this->pay($product, $price, $shipping, $description, $key);

    }

    /**
     * @param
     * $product 商品
     * $price 价钱
     * $shipping 运费
     * $description 描述内容
     */
    public function pay($product, $price, $shipping = 0, $description, $key)
    {
 
        $paypal = $this->PayPal;

        $total = $price + $shipping; //总价

        $payer = new Payer();

        $payer->setPaymentMethod('paypal');

        $item = new Item();
        $item->setName($product)->setCurrency(self::Currency)->setQuantity(1)->setPrice($price);

        $itemList = new ItemList();
        $itemList->setItems([$item]);

        $details = new Details();
        $details->setShipping($shipping)->setSubtotal($price);

        $amount = new Amount();
        $amount->setCurrency(self::Currency)->setTotal($total)->setDetails($details);

        $transaction = new Transaction();
        $follow_no   = get_order_sn();
        $transaction->setAmount($amount)->setItemList($itemList)->setDescription($description)->setInvoiceNumber($follow_no);
        $return_url   = 'http://'.request()->host(). '/Cash/paypalCallBack?follow_no='. $follow_no;
      
        $redirectUrls = new RedirectUrls();

        $redirectUrls->setReturnUrl($return_url . '&success=true')->setCancelUrl($return_url . '&success=false');

        // Create the WebProfile
        $presentation = new Presentation();
        $langs        = [
            1 => 'zh_CN',
            2 => 'en',
        ];
        $lang = $langs[getLangs(session("lang", 'zh_CN'))];

        $presentation->setLogoImage('http://'.request()->host()."/favicon.ico")
            ->setBrandName("Paypal Recharge")
            ->setLocaleCode($lang);
        $inputFields = new InputFields();
        $inputFields->setAllowNote(true)
            ->setNoShipping(1)
            ->setAddressOverride(0);
        $webProfile = new WebProfile();
        $webProfile->setName($product . uniqid())
            ->setPresentation($presentation)
            ->setInputFields($inputFields);
 
        try {
            $createdProfile   = $webProfile->create($paypal);
         
            $createdProfileID = json_decode($createdProfile);
             
            $profileid        = $createdProfileID->id;
 
            $payment = new Payment();
            $payment->setExperienceProfileId($profileid)->setIntent('sale')->setPayer($payer)->setRedirectUrls($redirectUrls)->setTransactions([$transaction]);

            $payment->create($paypal);
            $no = $payment->getId();
            
            Db::name('user_cash_rar')->where('id', $key)->update(['follow_no' => $follow_no]);
        } catch (PayPalConnectionException $e) {
            
            return response($e->getMessage().$e->getData());           
           
        }

        $approvalUrl = $payment->getApprovalLink(); 
         
        return $approvalUrl;     
    }

    /**
     * 回调
     */
    public function Callback()
    {
        Db::startTrans();

        try {
            // 修改订单状态
            $success = trim($_GET['success']);
            $err     = '';
            $code    = 0;

            if ($success == 'false' && !isset($_GET['paymentId']) && !isset($_GET['PayerID'])) {
                throw new Exception("Cancel payment", 1);

            }

            $paymentId = trim($_GET['paymentId']);
            $PayerID   = trim($_GET['PayerID']);

            if (!isset($success, $paymentId, $PayerID)) {

                throw new Exception("Failure to pay", 1);

            }

            if ((bool) $_GET['success'] === 'false') {

                throw new Exception('Failure to pay', 1);

            }

            $payment = Payment::get($paymentId, $this->PayPal);

            $execute = new PaymentExecution();

            $execute->setPayerId($PayerID);

            $r = $payment->execute($execute, $this->PayPal);

            $follow_no = $r->getTransactions()[0]->invoice_number;

            $this->dealPayed($follow_no, '');
            $code = 1;
            Db::commit();

        } catch (ValidateException $e) {
            Db::rollback();
            $err = $e->getMessage();
        } catch (PDOException $e) {
            Db::rollback();
            $err = $e->getMessage();
        } catch (Exception $e) {
            Db::rollback();
            $err = $e->getMessage();
        }

        return ['code' => $code, 'err' => $err];
    }

    public function notify($str)
    {
        if (!$str) {
            return;
        }
        Db::startTrans();
        try {

            parse_str($str, $info);

            $follow_no = $info['invoice'];

            $this->dealPayed($follow_no, $info);
            Db::commit();
        } catch (ValidateException $e) {
            Db::rollback();
            $err = $e->getMessage();
        } catch (PDOException $e) {
            Db::rollback();
            $err = $e->getMessage();
        } catch (Exception $e) {
            Db::rollback();
            $err = $e->getMessage();
        }

    }

/**
 * 增加金币记录，非现金
 * @return [type] [description]
 */
    public function dealPayed($follow_no, $str = '')
    {

        $info = \app\api\model\UserCashRar::where('follow_no', $follow_no)->find();
        if ($info->pay_flag == 0) {
            $total = $info->money;
            $time  = time();

            $before = Db::name("user")->where('u_id', $info->u_id)->lock(true)->value('money');
            Db::name('user_money_log')->insert([
                'op_type'     => 1,
                'op_key'      => $info->id,
                'before'      => $before,
                'plus'        => $total,
                'after'       => $before + $total,
                'op_type'     => 1,
                'create_time' => $time,
                'update_time' => $time,
                'memo'        => __('Recharge'),
                'u_id'        => $info->u_id,
            ]);
            $info->save(['check_flag' => 1, 'pay_flag' => 1, 'notify' => $str]);
            Db::name("user")->where('u_id', $info->u_id)->inc('money', $total)->update();
            //增加信用分
            \app\api\library\Credit::sceneLog($info->u_id,'recharge',['total'=>$info->cash,'uk'=>$follow_no]);
        }

    }

}
